﻿// HSS.ServiceModel.VirtualChannel.cs
// ----------------------------------------------------------------------------
// Licensed under the MIT license
// http://www.opensource.org/licenses/mit-license.html
// ----------------------------------------------------------------------------
// HighSpeed-Solutions, LLC
// Copyright (c) 2001-2010
// ----------------------------------------------------------------------------
// File:       VirtualChannel.cs
// Author:     HSS\gbanta
// Created:    08/12/2010
// Modified:   12/04/2010
// ----------------------------------------------------------------------------
namespace HSS.ServiceModel
{
	#region Using Directives
	using System;
	using System.Linq.Expressions;
	using System.ServiceModel;
	using HSS.ServiceModel.Internal;
	#endregion

	#region VirtualChannel<TContract>
	/// <summary>
	/// The VirtualChannel, exposes generic acccess to your WCF Services. The key benefit of the VirtualChannel is you do not need to generate or expose any proxy classes or asynchronous interfaces.
	/// </summary>
	/// <typeparam name="TContract">The service interface.</typeparam>
	/// <example>The sample below demonstrates using the VirtualChannel to query the employees for a given company id.
	/// <para>Before you can use the VirtualChannel it must be initialized. Typically this would be done during application start up.</para>
	/// <code>
	/// public partial class App : Application
	/// {
	///		public App()
	///		{
	///			this.Startup += this.Application_Startup;
	///			this.Exit += this.Application_Exit;
	///			this.UnhandledException += this.Application_UnhandledException;
	/// 
	///			InitializeComponent();
	///		}
	/// 
	///		private void Application_Startup(object sender, StartupEventArgs e)
	///		{
	///			this.RootVisual = new MainPage();
	///			
	///			// NOTE: This only has to be called once and is why it's located in the AppStartup section.
	///			// The servicePath must match what was registered with the VirtualServiceProvider.
	///			// The serviceType must match the Services Full Type Name (ex. Full.Namespace.Class).
	///			// The serviceToken must match what was registered with the VirtualServiceProvider.
	///			VirtualChannel&lt;ITestService&gt;.Initialize("services", "TestWebApp.TestService,TestWebApp", "some token or guid");
	///		}
	///	}
	/// </code>
	/// Then from a view model or view code behind class, you invoke your desired operation.
	/// <code>
	/// void GetEmployees(int companyId)
	/// {
	///		// The result Type is inferred as an IEnumerable&lt;Employee&gt; via the operations return value. Could be a list or a collection or a string etc.
	///		// as long as it matches the return type of the service method call.
	///		VirtualChannel&lt;ITestService&gt;.Invoke(s =&gt; s.GetEmployeesForCompany(companyId), (result, error) =>
	///		{
	///			if (null != error)
	///			{
	///				MessageBox.Show(error.Message);
	/// 			this.ModelItems = new ObservableCollection();
	/// 			return;
	/// 		}
	///				
	///			// The result is an IEnumerable&lt;Employee&gt;, as defined by the TypeParam.
	///			if (null != result)
	/// 			MessageBox.Show("Found [ " result.Count().ToString() + " ] employees.");
	///
	/// 		// Do something useful...
	/// 		this.ModelItems = new ObservableCollection(result);
	/// 			
	///		});
	///	}
	/// </code>
	/// </example>
#if !DEBUG
	[System.Diagnostics.DebuggerStepThroughAttribute()]
#endif
	public static class VirtualChannel<TContract>
		where TContract : class
	{
		#region Events
#if !SILVERLIGHT
		/// <summary>
		/// EVent fired when credentials are being requested.
		/// </summary>
		public static event EventHandler<GetGredentialEventArguments> PromptForCredentials;
#endif
		#endregion

		#region Fields
		private static Type VirtualFactoryType;
#if !SILVERLIGHT
		private static bool GetCredentials = true;
#endif
		#endregion

		#region Properties
		/// <summary>
		/// Gets if the VirtualChannel has been initialized.
		/// </summary>
		public static bool IsInitialized { get; private set; }
		/// <summary>
		/// Gets the Services Path.
		/// </summary>
		public static string ServicePath { get; private set; }
		/// <summary>
		/// Gets the Services TypeName.
		/// </summary>
		public static string ServiceTypeName { get; private set; }
		/// <summary>
		/// Gets the Service Token.
		/// </summary>
		public static string ServiceToken { get; private set; }
		/// <summary>
		/// Gets the Service's Endpoint Address.
		/// </summary>
		public static EndpointAddress ServiceEndpoint { get; private set; }
		/// <summary>
		/// Gets or sets the Default Communication Timeouts
		/// </summary>
		public static IDefaultCommunicationTimeouts Timeouts { get; set; }
#if !SILVERLIGHT
		/// <summary>
		/// Gets or sets the UserName.
		/// </summary>
		public static string UserName { get; set; }
		/// <summary>
		/// Gets or sets the Password.
		/// </summary>
		public static string Password { get; set; }
#endif

		#endregion

		#region Methods

		#region Initialization
		/// <summary>
		/// Initializes the VirtualChannel properties.
		/// </summary>
		/// <param name="serviceEndpoint">The EndpointAddress of the operation.</param>
		/// <param name="serviceToken">The token required to gain access to the service. Must match the token registered with the VirtualServiceProvider.</param>
		/// <param name="timeouts">The optional timeout values.</param>
		/// <remarks>
		/// <b>NOTE:</b> If already initialized, initialization is not repeated.
		/// </remarks>
		public static void Initialize(EndpointAddress serviceEndpoint, string serviceToken, IDefaultCommunicationTimeouts timeouts)
		{
			if (VirtualChannel<TContract>.IsInitialized)
				return;
			VirtualChannel<TContract>.IsInitialized = true;
			VirtualChannel<TContract>.VirtualFactoryType = VirtualChannelFactory.GetChannelFactoryType(typeof(TContract));
			VirtualChannel<TContract>.ServiceEndpoint = serviceEndpoint;
			VirtualChannel<TContract>.ServiceToken = serviceToken;
			VirtualChannel<TContract>.Timeouts = timeouts;
			VirtualChannel<TContract>.WarmupChannel();
		}
		/// <summary>
		/// Initializes the VirtualChannel properties.
		/// </summary>
		/// <param name="serviceEndpoint">The EndpointAddress of the operation.</param>
		/// <param name="serviceToken">The token required to gain access to the service. Must match the token registered with the VirtualServiceProvider.</param>
		/// <remarks>
		/// <b>NOTE:</b> If already initialized, initialization is not repeated.
		/// </remarks>
		public static void Initialize(EndpointAddress serviceEndpoint, string serviceToken)
		{
			if (VirtualChannel<TContract>.IsInitialized)
				return;
			VirtualChannel<TContract>.IsInitialized = true;
			VirtualChannel<TContract>.VirtualFactoryType = VirtualChannelFactory.GetChannelFactoryType(typeof(TContract));
			VirtualChannel<TContract>.ServiceEndpoint = serviceEndpoint;
			VirtualChannel<TContract>.ServiceToken = serviceToken;
			VirtualChannel<TContract>.WarmupChannel();
		}

#if SILVERLIGHT
		/// <summary>
		/// Initializes the VirtualChannel from an ChannelConfiguration instance.
		/// </summary>
		/// <param name="configuration">The <see cref="IChannelConfiguration"/> instance containing the initialization information.</param>
		/// <param name="timeouts">The optional timeout values.</param>
		/// <remarks>
		/// <b>NOTE:</b>If already initialized, initialization is not repeated.
		/// </remarks>
		public static void Initialize(IChannelConfiguration configuration, IDefaultCommunicationTimeouts timeouts)
		{
			if (VirtualChannel<TContract>.IsInitialized)
				return;
			if (null == configuration)
				throw new ArgumentNullException("configuration");
			VirtualChannel<TContract>.Initialize(configuration.ServicePath, configuration.ServiceTypeName, configuration.ServiceToken, timeouts);
		}
		/// <summary>
		/// Initializes the VirtualChannel from an ChannelConfiguration instance.
		/// </summary>
		/// <param name="configuration">The <see cref="IChannelConfiguration"/> instance containing the initialization information.</param>
		/// <remarks>
		/// <b>NOTE:</b>If already initialized, initialization is not repeated.
		/// </remarks>
		public static void Initialize(IChannelConfiguration configuration)
		{
			if (VirtualChannel<TContract>.IsInitialized)
				return;
			if (null == configuration)
				throw new ArgumentNullException("configuration");
			VirtualChannel<TContract>.Initialize(configuration.ServicePath, configuration.ServiceTypeName, configuration.ServiceToken);
		}
		/// <summary>
		/// Initializes the VirtualChannel properties.
		/// </summary>
		/// <param name="servicePath">The relative uri path to a virtual services directory registered with the VirtualServiceProvider. (ex: services or /services).</param>
		/// <param name="serviceTypeName">The namespace qualifed Type of the Service (ex. Full.NameSpace.ClassName).</param>
		/// <param name="serviceToken">The token required to gain access to the service. Must match the token registered with the VirtualServiceProvider.</param>
		/// <param name="timeouts">The optional timeout values.</param>
		/// <remarks>
		/// <b>NOTE:</b> If already initialized, initialization is not repeated.
		/// </remarks>
		public static void Initialize(string servicePath, string serviceTypeName, string serviceToken, IDefaultCommunicationTimeouts timeouts)
		{
			if (VirtualChannel<TContract>.IsInitialized)
				return;
			VirtualChannel<TContract>.IsInitialized = true;
			VirtualChannel<TContract>.VirtualFactoryType = VirtualChannelFactory.GetChannelFactoryType(typeof(TContract));
			VirtualChannel<TContract>.ServicePath = servicePath;
			VirtualChannel<TContract>.ServiceTypeName = serviceTypeName;
			VirtualChannel<TContract>.ServiceToken = serviceToken;
			VirtualChannel<TContract>.ServiceEndpoint = VirtualServiceHelper.GetEndpoint(ServicePath, ServiceTypeName);
			VirtualChannel<TContract>.Timeouts = timeouts;
			VirtualChannel<TContract>.WarmupChannel();
		}
		/// <summary>
		/// Initializes the VirtualChannel properties.
		/// </summary>
		/// <param name="servicePath">The relative uri path to a virtual services directory registered with the VirtualServiceProvider. (ex: services or /services).</param>
		/// <param name="serviceTypeName">The namespace qualifed Type of the Service (ex. Full.NameSpace.ClassName).</param>
		/// <param name="serviceToken">The token required to gain access to the service. Must match the token registered with the VirtualServiceProvider.</param>
		/// <remarks>
		/// <b>NOTE:</b> If already initialized, initialization is not repeated.
		/// </remarks>
		public static void Initialize(string servicePath, string serviceTypeName, string serviceToken)
		{
			if (VirtualChannel<TContract>.IsInitialized)
				return;
			VirtualChannel<TContract>.IsInitialized = true;
			VirtualChannel<TContract>.VirtualFactoryType = VirtualChannelFactory.GetChannelFactoryType(typeof(TContract));
			VirtualChannel<TContract>.ServicePath = servicePath;
			VirtualChannel<TContract>.ServiceTypeName = serviceTypeName;
			VirtualChannel<TContract>.ServiceToken = serviceToken;
			VirtualChannel<TContract>.ServiceEndpoint = VirtualServiceHelper.GetEndpoint(ServicePath, ServiceTypeName);
			VirtualChannel<TContract>.WarmupChannel();
		}
#else
		/// <summary>
		/// Initializes the VirtualChannel properties.
		/// </summary>
		/// <param name="serviceEndpoint">The EndpointAddress of the operation.</param>
		/// <param name="serviceToken">The token required to gain access to the service. Must match the token registered with the VirtualServiceProvider.</param>
		/// <param name="userName">The users UserName.</param>
		/// <param name="password">The users Password.</param>
		/// <param name="timeouts">The optional timeout values.</param>
		/// <remarks>
		/// <b>NOTE:</b> If already initialized, initialization is not repeated.
		/// </remarks>
		public static void Initialize(EndpointAddress serviceEndpoint, string serviceToken, string userName, string password, IDefaultCommunicationTimeouts timeouts)
		{
			if (VirtualChannel<TContract>.IsInitialized)
				return;
			VirtualChannel<TContract>.IsInitialized = true;
			VirtualChannel<TContract>.VirtualFactoryType = VirtualChannelFactory.GetChannelFactoryType(typeof(TContract));
			VirtualChannel<TContract>.ServiceEndpoint = serviceEndpoint;
			VirtualChannel<TContract>.ServiceToken = serviceToken;
			VirtualChannel<TContract>.UserName = userName;
			VirtualChannel<TContract>.Password = password;
			VirtualChannel<TContract>.Timeouts = timeouts;
			VirtualChannel<TContract>.WarmupChannel();
		}
		/// <summary>
		/// Initializes the VirtualChannel properties.
		/// </summary>
		/// <param name="serviceEndpoint">The EndpointAddress of the operation.</param>
		/// <param name="serviceToken">The token required to gain access to the service. Must match the token registered with the VirtualServiceProvider.</param>
		/// <param name="userName">The users UserName.</param>
		/// <param name="password">The users Password.</param>
		/// <remarks>
		/// <b>NOTE:</b> If already initialized, initialization is not repeated.
		/// </remarks>
		public static void Initialize(EndpointAddress serviceEndpoint, string serviceToken, string userName, string password)
		{
			if (VirtualChannel<TContract>.IsInitialized)
				return;
			VirtualChannel<TContract>.IsInitialized = true;
			VirtualChannel<TContract>.VirtualFactoryType = VirtualChannelFactory.GetChannelFactoryType(typeof(TContract));
			VirtualChannel<TContract>.ServiceEndpoint = serviceEndpoint;
			VirtualChannel<TContract>.ServiceToken = serviceToken;
			VirtualChannel<TContract>.UserName = userName;
			VirtualChannel<TContract>.Password = password;
			VirtualChannel<TContract>.WarmupChannel();
		}
#endif

		#endregion

		#region Invoke Overloads

		#region Static API

		/// <summary>
		/// Invokes the requested <see cref="Action&lt;TContract&gt;"/> operation.
		/// </summary>
		/// <param name="operation">The <see cref="Expression&lt;T&gt;"/> that defines the service operation to call.</param>
		/// <example>The sample below demonstrates calling the Invoke method with an Action expression and NO callback (fire and forget).
		/// <code>
		/// VirtualChannel&lt;ITestService&gt;.Invoke(s =&gt; s.SomeVoidMethod());
		/// </code>
		/// </example>
		/// <exception cref="VirtualChannelNotInitializedException">Cannot access the VirtualChannel until it has been initialized.</exception>
		public static void Invoke(Expression<Action<TContract>> operation)
		{
			if (!IsInitialized)
				throw new VirtualChannelNotInitializedException();

			var op = new VirtualActionOperation<TContract>(VirtualFactoryType, ServiceEndpoint, ServiceToken, Timeouts);
#if !SILVERLIGHT
			EnsureCredentials();
			op.UserName = VirtualChannel<TContract>.UserName;
			op.Password = VirtualChannel<TContract>.Password;
#endif
			op.Invoke(operation, null);
		}
		/// <summary>
		/// Invokes the requested <see cref="Action&lt;TContract&gt;"/> operation.
		/// </summary>
		/// <param name="operation">The <see cref="Expression&lt;T&gt;"/> that defines the service operation to call.</param>
		/// <param name="callback">The <see cref="ChannelActionCompleted"/> delegate.</param>
		/// <example>The sample below demonstrates calling the Invoke method with an Action expression.
		/// <code>
		/// VirtualChannel&lt;ITestService&gt;.Invoke(s =&gt; s.SomeVoidMethod(), (error) =&gt;
		/// {
		/// 	if (null != error)
		/// 	{
		/// 		MessageBox.Show(error.Message);
		/// 		return;
		/// 	}
		/// 	// Do something useful...
		/// });
		/// </code>
		/// </example>
		/// <exception cref="VirtualChannelNotInitializedException">Cannot access the VirtualChannel until it has been initialized.</exception>
		public static void Invoke(Expression<Action<TContract>> operation, ChannelActionCompleted callback)
		{
			if (!IsInitialized)
				throw new VirtualChannelNotInitializedException();

			var op = new VirtualActionOperation<TContract>(VirtualFactoryType, ServiceEndpoint, ServiceToken, Timeouts);
#if !SILVERLIGHT
			EnsureCredentials();
			op.UserName = VirtualChannel<TContract>.UserName;
			op.Password = VirtualChannel<TContract>.Password;
#endif
			op.Invoke(operation, callback);
		}
		/// <summary>
		/// Invokes the requested <see cref="Action&lt;TContract&gt;"/> operation.
		/// </summary>
		/// <typeparam name="TState">The Type of the provided user state.</typeparam>
		/// <param name="operation">The <see cref="Expression&lt;T&gt;"/> that defines the service operation to call.</param>
		/// <param name="userState">Any user provided state to be passed thru to the callback.</param>
		/// <param name="callback">The <see cref="ChannelActionCompleted"/> delegate, which provides confirmation that the operation completed and any exceptions that may have been encountered along with user provided state.</param>
		/// <example>The sample below demonstrates calling the Invoke method with an Action expression with State.
		/// <code>
		/// VirtualChannel&lt;ITestService&gt;.Invoke&lt;string&gt;(s =&gt; s.SomeVoidMethod(), "my user state", (error, userState) =&gt;
		/// {
		/// 	if (null != error)
		/// 	{
		/// 		MessageBox.Show(error.Message);
		/// 		return;
		/// 	}
		/// 	
		///		MessageBox.Show("userState = " + userState);
		/// 	
		/// 	// Do something useful...
		/// });
		/// </code>
		/// </example>
		/// <exception cref="VirtualChannelNotInitializedException">Cannot access the VirtualChannel until it has been initialized.</exception>
		public static void Invoke<TState>(Expression<Action<TContract>> operation, TState userState, ChannelActionCompleted<TState> callback)
		{
			if (!IsInitialized)
				throw new VirtualChannelNotInitializedException();

			var op = new VirtualActionOperation<TContract, TState>(VirtualFactoryType, ServiceEndpoint, ServiceToken, Timeouts);
#if !SILVERLIGHT
			EnsureCredentials();
			op.UserName = VirtualChannel<TContract>.UserName;
			op.Password = VirtualChannel<TContract>.Password;
#endif
			op.Invoke(operation, callback, userState);
		}

		/// <summary>
		/// Invokes the requested <see cref="Func&lt;TContract, TResult&gt;"/> operation.
		/// </summary>
		/// <typeparam name="TResult">The Type of the object expected as a result of calling the operation.</typeparam>
		/// <param name="operation">The <see cref="Expression&lt;T&gt;"/> that defines the service operation to call.</param>
		/// <param name="callback">The <see cref="ChannelFuncCompleted&lt;TResult&gt;"/> delegate, which provides confirmation that the operation completed, the result of the operation and any exceptions that may have been encountered.</param>
		/// <example>The sample below demonstrates calling the Invoke method with an Func expression.
		/// <code>
		/// void GetEmployees(int companyId)
		/// {
		///		// Here we define the result as an IEnumerable&lt;Employee&gt; via the TypeParam. Could be a list or a collection or a string etc.
		///		// as long as it matches the return type of the service method call.
		///		VirtualChannel&lt;ITestService&gt;.Invoke&lt;IEnumerable&lt;Employee&gt;&gt;(s =&gt; s.GetEmployeesForCompany(companyId), (result, error) =>
		///		{
		/// 		if (null != error)
		/// 		{
		/// 			MessageBox.Show(error.Message);
		/// 			this.ModelItems = new ObservableCollection();
		/// 			return;
		/// 		}
		///				
		///			// The result is an IEnumerable&lt;Employee&gt;, as defined by the InvokeFuncAsync TypeParam.
		///			if (null != result)
		/// 			MessageBox.Show("Found [ " result.Count().ToString() + " ] employees.");
		///
		/// 		// Do something useful...
		/// 		this.ModelItems = new ObservableCollection(result);
		/// 			
		///		});
		///	}
		/// </code>
		/// </example>
		/// <exception cref="VirtualChannelNotInitializedException">Cannot access the VirtualChannel until it has been initialized.</exception>
		public static void Invoke<TResult>(Expression<Func<TContract, TResult>> operation, ChannelFuncCompleted<TResult> callback)
		{

			if (!IsInitialized)
				throw new VirtualChannelNotInitializedException();

			var op = new VirtualFuncOperation<TContract, TResult>(VirtualFactoryType, ServiceEndpoint, ServiceToken, Timeouts);
#if !SILVERLIGHT
			EnsureCredentials();
			op.UserName = VirtualChannel<TContract>.UserName;
			op.Password = VirtualChannel<TContract>.Password;
#endif
			op.Invoke(operation, callback);

		}
		/// <summary>
		/// Invokes the requested <see cref="Func&lt;TContract, TResult&gt;"/> operation.
		/// </summary>
		/// <typeparam name="TResult">The Type of the object expected as a result of calling the operation.</typeparam>
		/// <typeparam name="TState">The Type of the provided user state.</typeparam>
		/// <param name="operation">The <see cref="Expression&lt;T&gt;"/> that defines the service operation to call.</param>
		/// <param name="userState">Any user provided state to be passed thru to the callback.</param>
		/// <param name="callback">The <see cref="ChannelFuncCompleted&lt;TResult,TState&gt;"/> delegate, which provides confirmation that the operation completed, the result of the operation, the user stated provided, and any exceptions that may have been encountered.</param>
		/// <example>The sample below demonstrates calling the Invoke method with an Func expression with State.
		/// <code>
		/// void GetEmployees(int companyId)
		/// {
		///		// Here we define the result as an IEnumerable&lt;Employee&gt; via the TypeParam. Could be a list or a collection or a string etc.
		///		// as long as it matches the return type of the service method call.
		///		VirtualChannel&lt;ITestService&gt;.Invoke&lt;IEnumerable&lt;Employee&gt;, string&gt;(s =&gt; s.GetEmployeesForCompany(companyId), "my user state", (result, error, userState) =>
		///		{
		/// 		if (null != error)
		/// 		{
		/// 			MessageBox.Show(error.Message);
		/// 			this.ModelItems = new ObservableCollection();
		/// 			return;
		/// 		}
		///				
		/// 		MessageBox.Show("userState = " + userState);
		/// 		
		///			// The result is an IEnumerable&lt;Employee&gt;, as defined by the InvokeFuncAsync TypeParam.
		///			if (null != result)
		/// 			MessageBox.Show("Found [ " result.Count().ToString() + " ] employees.");
		///
		/// 		// Do something useful...
		/// 		this.ModelItems = new ObservableCollection(result);
		/// 			
		///		});
		///	}
		/// </code>
		/// </example>
		/// <exception cref="VirtualChannelNotInitializedException">Cannot access the VirtualChannel until it has been initialized.</exception>
		public static void Invoke<TResult, TState>(Expression<Func<TContract, TResult>> operation, TState userState, ChannelFuncCompleted<TResult, TState> callback)
		{
			if (!IsInitialized)
				throw new VirtualChannelNotInitializedException();

			var op = new VirtualFuncOperation<TContract, TResult, TState>(VirtualFactoryType, ServiceEndpoint, ServiceToken, Timeouts);
#if !SILVERLIGHT
			EnsureCredentials();
			op.UserName = VirtualChannel<TContract>.UserName;
			op.Password = VirtualChannel<TContract>.Password;
#endif
			op.Invoke(operation, callback, userState);
		}

		#endregion

		#endregion

#if !SILVERLIGHT

		/// <summary>
		/// Clear the current credentials.
		/// </summary>
		public static void ResetCredentials()
		{
			VirtualChannel<TContract>.GetCredentials = true;
			VirtualChannel<TContract>.UserName = string.Empty;
			VirtualChannel<TContract>.Password = string.Empty;
		}

		/// <summary>
		/// Attempt to retrieve the credentials.
		/// </summary>
		private static void EnsureCredentials()
		{
			if (GetCredentials)
			{
				var handler = VirtualChannel<TContract>.PromptForCredentials;
				if (null != handler)
				{
					var e = new GetGredentialEventArguments();
					handler(null, e);
					if (e.GetCredentialCompleted)
						VirtualChannel<TContract>.GetCredentials = false;
					try
					{
						VirtualChannel<TContract>.UserName = e.UserName;
						VirtualChannel<TContract>.Password = e.Password;
					}
					catch { }
				}
			}
		}

#endif

		private static void WarmupChannel()
		{
#if !SILVERLIGHT
			var binding = VirtualServiceHelper.GetBinding(ServiceEndpoint, ServiceToken, UserName, Password);
#else
			var binding = VirtualServiceHelper.GetBinding(ServiceEndpoint, ServiceToken);
#endif
			dynamic factory = Activator.CreateInstance(VirtualChannel<TContract>.VirtualFactoryType, binding, VirtualChannel<TContract>.ServiceEndpoint);
			var channel = factory.CreateChannel();
			if (null != channel)
				((System.ServiceModel.Channels.IChannel)channel).Close();
			if (null != factory)
				factory.Close();
		}

		#endregion
	}
	#endregion

	#region GetGredentialEventArguments
#if !SILVERLIGHT
	/// <summary>
	/// GetGredentialEventArguments
	/// </summary>
	public class GetGredentialEventArguments : EventArgs
	{
	#region Constructors
		/// <summary>
		/// Constructor
		/// </summary>
		public GetGredentialEventArguments()
		{
			GetCredentialCompleted = false;
			UserName = string.Empty;
			Password = string.Empty;
		}
	#endregion

	#region Properties
		/// <summary>
		/// Gets or sets whether or not to continue checking for Credentials.
		/// </summary>
		public bool GetCredentialCompleted { get; set; }
		/// <summary>
		/// Gets or sets the users UserName.
		/// </summary>
		public string UserName { get; set; }
		/// <summary>
		/// Gets or sets the users Password.
		/// </summary>
		public string Password { get; set; }
	#endregion
	}
#endif
	#endregion
}